package vp.imagefilter;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;


import jjil.core.RgbImage;
import jjil.android.*;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.util.FloatMath;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity implements OnClickListener {

	
	private static final int CAMERA_ACTIVITY1 = 0;
	private static final int CAMERA_ACTIVITY2 = 1;
	
	static double RWGT = 0.3086;
	static double GWGT = 0.6094;
	static double BWGT = 0.0820;


	Button b1;
	Button b2;
	Button combine;
	ImageView im;
	
	Intent cameraIntent;
	Bitmap image1;
	Bitmap image2;
	String fileLoc;
	

	    @Override
	    public void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);
	        setContentView(R.layout.main);
	        
	        b1 = (Button)findViewById(R.id.takePhoto1);
	        b2 = (Button) findViewById(R.id.takePhoto2);
	        combine = (Button) findViewById(R.id.combine);
	        
	        im = (ImageView) findViewById(R.id.combinedImage);
	        b1.setOnClickListener(this);
	        b2.setOnClickListener(this);
	        combine.setOnClickListener(this);

	    }


		@Override
		public void onClick(View arg0) {
			// TODO Auto-generated method stub
			fileLoc = Environment.getExternalStorageDirectory().getAbsolutePath() +  System.currentTimeMillis() + ".jpg";
			cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
			if(arg0.getId() == R.id.takePhoto1)
			{
			 
			
			cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, 
	     	Uri.fromFile(new File("/sdcard/tmp"))); 
			startActivityForResult(cameraIntent, CAMERA_ACTIVITY1);
			
			
			}else if(arg0.getId() == R.id.takePhoto2)
			{
				 
				 
				cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, 
						Uri.fromFile(new File("/sdcard/tmp"))); 
				startActivityForResult(cameraIntent, CAMERA_ACTIVITY2);
			}else
			{
				
				image1 = getResizedBitmap(image1, 640, 853);
				double[] template={(1/9.0),(1/9.0),(1/9.0),
								   (1/9.0),(1/9.0),(1/9.0),
								   (1/9.0),(1/9.0),(1/9.0)}; 
			    //convolve(template, 3, 3); 
				
				//grayscale();
				 //sepia2();
				 //contrast(1.2);
				// softedges();
				//border();
				//roundBorderWithLib();
				saturate(.2);
				roundBorderWithAndroid();
			    im.setImageBitmap(image1);
			    
			    String url = Images.Media.insertImage(getContentResolver(), image1, "testIMage", null);
			}
		}
	
		
		@Override
		protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
			super.onActivityResult(requestCode, resultCode, intent);
			
			if (resultCode == RESULT_CANCELED) {
				//showToast(this,"Activity cancelled");
				return;
			}	
			
			  FileInputStream in;
		        BufferedInputStream buf;
		        File fi = new File("/sdcard/tmp");
			switch (requestCode) {		
			case CAMERA_ACTIVITY1: 
				
		        try {
		       	    in = new FileInputStream("/sdcard/tmp");
		            buf = new BufferedInputStream(in);
		            image1 = BitmapFactory.decodeStream(buf);
		            //image.setImageBitmap(bMap);
		            if (in != null) {
		         	in.close();
		            }
		            if (buf != null) {
		         	buf.close();
		            }
		        } catch (Exception e) {
		            Log.d("Error reading file", e.toString());
		        }
				break;
			case CAMERA_ACTIVITY2: 
				try {
					in = new FileInputStream("/sdcard/tmp");
		            buf = new BufferedInputStream(in);
		            image2 = BitmapFactory.decodeStream(buf);
		            //image.setImageBitmap(bMap);
		            if (in != null) {
		         	in.close();
		            }
		            if (buf != null) {
		         	buf.close();
		            }
		        } catch (Exception e) {
		            Log.d("Error reading file", e.toString());
		        }
				break;
			}
		}
		
		public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {

			int width = bm.getWidth();
	
			int height = bm.getHeight();

			float scaleWidth = ((float) newWidth) / width;

			float scaleHeight = ((float) newHeight) / height;

			// CREATE A MATRIX FOR THE MANIPULATION

			Matrix matrix = new Matrix();

			// RESIZE THE BIT MAP

			matrix.postScale(scaleWidth, scaleHeight);

			// RECREATE THE NEW BITMAP

			Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);

			return resizedBitmap;
	
			}
		

	public void convolve(double[] mat, int rows, int cols) {
		if ((rows % 2) == 0 || (cols % 2) == 0) {
		} else {
			// start = (int) System.currentTimeMillis();

			RgbImage mRgbImage = RgbImageAndroid.toRgbImage(image1);
			int width = image1.getWidth();
			int height = image1.getHeight();
			int[] rgbData = mRgbImage.getData();
			int[] conv = new int[width * height];
			int sumR = 0;
			int sumG = 0;
			int sumB = 0;

			RgbImage prevRgbImage = (RgbImage) mRgbImage.clone();

			for (int x = (cols - 1) / 2; x < width - (cols + 1) / 2; x++) {
				for (int y = (rows - 1) / 2; y < height - (rows + 1) / 2; y++) {
					sumR = 0;
					sumG = 0;
					sumB = 0;
					for (int x1 = 0; x1 < cols; x1++) {
						for (int y1 = 0; y1 < rows; y1++) {
							int x2 = (x - (cols - 1) / 2 + x1);
							int y2 = (y - (rows - 1) / 2 + y1);
							int R = ((rgbData[y2 * width + x2] >> 16) & 0xff);
							int G = ((rgbData[y2 * width + x2] >> 8) & 0xff);
							int B = ((rgbData[y2 * width + x2]) & 0xff);

							sumR += R * (mat[y1 * cols + x1]);
							sumG += G * (mat[y1 * cols + x1]);
							sumB += B * (mat[y1 * cols + x1]);
						}
					}

					conv[y * width + x] = 0xff000000 | ((int) sumR << 16
							| (int) sumG << 8 | (int) sumB);
				}
			}
			System.arraycopy(conv, 0, rgbData, 0, width * height);
			// end = (int) System.currentTimeMillis();
			
			image1 = RgbImageAndroid.toBitmap(mRgbImage);
		}

	}
	
	public void sepia() {
	
			// start = (int) System.currentTimeMillis();

			RgbImage mRgbImage = RgbImageAndroid.toRgbImage(image1);
			int width = image1.getWidth();
			int height = image1.getHeight();
			int[] rgbData = mRgbImage.getData();
			int[] conv = new int[width * height];
			int sumR = 0;
			int sumG = 0;
			int sumB = 0;


			for (int x = 0; x < width; x++) {
				for (int y = 0; y < height; y++) {
					sumR = 0;
					sumG = 0;
					sumB = 0;

							int R = ((rgbData[y * width + x] >> 16) & 0xff);
							int G = ((rgbData[y * width + x] >> 8) & 0xff);
							int B = ((rgbData[y * width + x]) & 0xff);
							
							
							
						
								//sumR = (int) (R * 0.75  + G * 0.45 + B * 0.05);
								//sumG = (int) (R * 0.50  + G * 0.25 + B * 0.04);					 
								//sumB = (int) (R * 0.08  + G * 0.04 + B * 0.03);
								
								if(sumR > 255)
								{	
									sumR = 255;
								}
								
								if(sumG > 255)
								{	
									sumG = 255;
								}
								
								if(sumB > 255)
								{	
									sumB = 255;
								}



							//sumR = (int) (R * 0.393  + G * 0.679 + B * 0.189);
							//sumG = (int) (R * 0.349  + G * 0.686 + B * 0.168);
							//sumB = (int) (R * 0.272  + G * 0.534 + B * 0.131);
							
							//sumR = (int) (R * 0.75  + G * 0.45 + B * 0.05);
							//sumG = (int) (R * 0.50  + G * 0.25 + B * 0.04);					 
							//sumB = (int) (R * 0.08  + G * 0.04 + B * 0.03);


					conv[y * width + x] = 0xff000000 | ((int) sumR << 16
							| (int) sumG << 8 | (int) sumB);
				}
			}
			System.arraycopy(conv, 0, rgbData, 0, width * height);
			// end = (int) System.currentTimeMillis();
			
			image1 = RgbImageAndroid.toBitmap(mRgbImage);
		}
	
	public void grayscale() {
		
		// start = (int) System.currentTimeMillis();

		RgbImage mRgbImage = RgbImageAndroid.toRgbImage(image1);
		int width = image1.getWidth();
		int height = image1.getHeight();
		int[] rgbData = mRgbImage.getData();
		int[] conv = new int[width * height];
		int sumR = 0;
		int sumG = 0;
		int sumB = 0;


		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				sumR = 0;
				sumG = 0;
				sumB = 0;

						int R = ((rgbData[y * width + x] >> 16) & 0xff);
						int G = ((rgbData[y * width + x] >> 8) & 0xff);
						int B = ((rgbData[y * width + x]) & 0xff);
						
						
						
					
							



						//sumR = (int) (R * 0.393  + G * 0.679 + B * 0.189);
						//sumG = (int) (R * 0.349  + G * 0.686 + B * 0.168);
						//sumB = (int) (R * 0.272  + G * 0.534 + B * 0.131);
						
						//sumR = (int) (R * 0.75  + G * 0.45 + B * 0.05);
						//sumG = (int) (R * 0.50  + G * 0.25 + B * 0.04);					 
						//sumB = (int) (R * 0.08  + G * 0.04 + B * 0.03);


				conv[y * width + x] = 0xff000000 | (((R + G + B)/3) << 16)
						| (((R + G + B)/3) << 8) | ((R + G + B)/3);
			}
		}
		System.arraycopy(conv, 0, rgbData, 0, width * height);
		// end = (int) System.currentTimeMillis();
		
		image1 = RgbImageAndroid.toBitmap(mRgbImage);
	}
	
	
public void border() {
		
		// start = (int) System.currentTimeMillis();

		RgbImage mRgbImage = RgbImageAndroid.toRgbImage(image1);
		int width = image1.getWidth();
		int height = image1.getHeight();
		int[] rgbData = mRgbImage.getData();
		int[] conv = new int[width * height];
		int sumR = 0;
		int sumG = 0;
		int sumB = 0;


		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				sumR = 0;
				sumG = 0;
				sumB = 0;
				
				int R = ((rgbData[y * width + x] >> 16) & 0xff);
				int G = ((rgbData[y * width + x] >> 8) & 0xff);
				int B = ((rgbData[y * width + x]) & 0xff);

						if (x < 20 || y < 20 || x > (width-20) || y > (height - 20))
						{
							conv[y * width + x] = 0xff000000 | 255;
						}else
						{
							conv[y * width + x] = 0xff000000 | ((R) << 16)
							| ((G) << 8) | ((B));
						}
			}
		}
		System.arraycopy(conv, 0, rgbData, 0, width * height);
		// end = (int) System.currentTimeMillis();
		
		image1 = RgbImageAndroid.toBitmap(mRgbImage);
	}

public void roundBorderWithLib() {
	
	// start = (int) System.currentTimeMillis();

	RgbImage mRgbImage = RgbImageAndroid.toRgbImage(image1);
	int width = image1.getWidth();
	int height = image1.getHeight();
	int[] rgbData = mRgbImage.getData();
	int[] conv = new int[width * height];
	int sumR = 0;
	int sumG = 0;
	int sumB = 0;


	for (int x = 0; x < width; x++) {
		for (int y = 0; y < height; y++) {
			sumR = 0;
			sumG = 0;
			sumB = 0;
			
			int R = ((rgbData[y * width + x] >> 16) & 0xff);
			int G = ((rgbData[y * width + x] >> 8) & 0xff);
			int B = ((rgbData[y * width + x]) & 0xff);
			
			
			if(x < 60 && y < 60)
			{
				if(x < (60 - FloatMath.sqrt((-(y*y) + (40*40)))))
				{
					conv[y * width + x] = 0xff000000 | 255;
				}
				
			}else
			{
				
				conv[y * width + x] = 0xff000000 | ((R) << 16)
				| ((G) << 8) | ((B));
			}				
					
		}
	}
	System.arraycopy(conv, 0, rgbData, 0, width * height);
	// end = (int) System.currentTimeMillis();
	
	image1 = RgbImageAndroid.toBitmap(mRgbImage);
}



public void roundBorderWithAndroid() {
	 int w = image1.getWidth();
	    int h = image1.getHeight();
	
	    image1 = image1.copy(Bitmap.Config.ARGB_8888, true);
	//Bitmap bitmapResult = image1.copy(Bitmap.Config config, boolean isMutable)
    //image1 = bitmapResult;
	
	Path clipPath = new Path();

    clipPath.addRoundRect(new RectF(0,0,w,h), 50.0f, 50.0f, Path.Direction.CW);
    clipPath.addRect(new RectF(0,0,w,h), Path.Direction.CW);
    
    
    Canvas c = new Canvas(image1);
    Paint paint = new Paint();
    
    paint.setStrokeWidth(20);
    
    paint.setARGB(255, 0, 0, 0);
    paint.setStyle(Paint.Style.STROKE);
   
    
    c.drawPath(clipPath, paint);
    
    
   
}

public void contrast()
{
	double[][] arr = {{.8, 0, 0, 0},
			          {0, .8, 0, 0},
			          {0, 0, .8, 0},
			          {0, 0, 0, 1}};
     
	linearOp(arr);
	
}

public void contrast(double c)
{
	double[][] arr = {{c, 0, 0, 0},
			          {0, c, 0, 0},
			          {0, 0, c, 0},
			          {0, 0, 0, 1}};
     
	linearOp(arr);
	
}

public void sepia2()
{
	

	
	double[][] arr = {{0.85, 0.55,0.06, 0},
			          {0.60, 0.35, 0.05, 0},
			          {0.60,  0.05, 0.04, 0},
			          {0, 0, 0, 1}};
     
	linearOp(arr);
	
}

public void saturate(double s)
{
	

	
	double[][] arr = {{(1.0-s)*RWGT + s, (1.0-s)*RWGT,(1.0-s)*RWGT, 0},
			          {(1.0-s)*GWGT, (1.0-s)*GWGT + s,(1.0-s)*GWGT, 0},
			          {(1.0-s)*BWGT,  (1.0-s)*BWGT, (1.0-s)*BWGT + s, 0},
			          {0, 0, 0, 1}};
     
	linearOp(arr);
	
}


public void sepia2sep()
{
	

	
	double[][] arr = {{0.75, 0.45,0.05, 0},
			          {0.50, 0.25, 0.04, 0},
			          {0.50,  0.04, 0.03, 0},
			          {0, 0, 0, 1}};
     
	linearOp(arr);
	
}




public void linearOp(double[][] mat) {
	RgbImage mRgbImage = RgbImageAndroid.toRgbImage(image1);
	int width = image1.getWidth();
	int height = image1.getHeight();
	int[] rgbData = mRgbImage.getData();
	int[] conv = new int[width * height];
	int sumR = 0;
	int sumG = 0;
	int sumB = 0;


	for (int x = 0; x < width; x++) {
		for (int y = 0; y < height; y++) {
			sumR = 0;
			sumG = 0;
			sumB = 0;

					int r = ((rgbData[y * width + x] >> 16) & 0xff);
					int g = ((rgbData[y * width + x] >> 8) & 0xff);
					int b = ((rgbData[y * width + x]) & 0xff);
					
					
					sumR  = (int) (r*mat[0][0] + g*mat[1][0] +
				    b*mat[2][0] + mat[3][0]);
					sumG = (int) (r*mat[0][1] + g*mat[1][1] +
				    b*mat[2][1] + mat[3][1]);
					sumB = (int) (r*mat[0][2] + g*mat[1][2] +
				    b*mat[2][2] + mat[3][2]);
				
						
						if(sumR > 255)
						{	
							sumR = 255;
						}
						
						if(sumG > 255)
						{	
							sumG = 255;
						}
						
						if(sumB > 255)
						{	
							sumB = 255;
						}


			conv[y * width + x] = 0xff000000 | ((int) sumR << 16
					| (int) sumG << 8 | (int) sumB);
		}
	}
	System.arraycopy(conv, 0, rgbData, 0, width * height);
	// end = (int) System.currentTimeMillis();
	
	image1 = RgbImageAndroid.toBitmap(mRgbImage);
	
}


public void softedges() {
	
	// start = (int) System.currentTimeMillis();

	RgbImage mRgbImage = RgbImageAndroid.toRgbImage(image1);
	int width = image1.getWidth();
	int height = image1.getHeight();
	int[] rgbData = mRgbImage.getData();
	int[] conv = new int[width * height];
	int sumR = 0;
	int sumG = 0;
	int sumB = 0;
	int edgeDis = (int) (.5 * width);

  Log.d("IMAGE P", "" + edgeDis);
	for (int x = 0; x < width; x++) {
		for (int y = 0; y < height; y++) {
			sumR = 0;
			sumG = 0;
			sumB = 0;

					int R = ((rgbData[y * width + x] >> 16) & 0xff);
					int G = ((rgbData[y * width + x] >> 8) & 0xff);
					int B = ((rgbData[y * width + x]) & 0xff);
					
					
					double multi = (double)x/(edgeDis);
					
					if(x  > width -  edgeDis)
					{
						multi = (double)(width-x)/(edgeDis);
					}
					

					
					if(multi > 1)
					{
						multi = 1;
					}
				
				
						sumR = (int) (R * multi + G * 0 + B * 0);
						sumG = (int) (R * 0  + G * multi + B * 0);					 
						sumB = (int) (R * 0  + G * 0 + B * multi);
						
						if(sumR > 255)
						{	
							sumR = 255;
						}
						
						if(sumG > 255)
						{	
							sumG = 255;
						}
						
						if(sumB > 255)
						{	
							sumB = 255;
						}


			conv[y * width + x] = 0xff000000 | ((int) sumR << 16
					| (int) sumG << 8 | (int) sumB);
		}
	}
	System.arraycopy(conv, 0, rgbData, 0, width * height);
	// end = (int) System.currentTimeMillis();
	
	image1 = RgbImageAndroid.toBitmap(mRgbImage);
}
}
